package cn.sylinx.horm.config;

import java.util.concurrent.atomic.AtomicBoolean;

import cn.sylinx.horm.core.interceptor.SqlClientInterceptor;
import cn.sylinx.horm.core.stat.SqlStatManager;
import cn.sylinx.horm.exception.HORMException;
import cn.sylinx.horm.proxy.command.interceptor.CommandInterceptor;
import cn.sylinx.horm.proxy.mapper.interceptor.MapperInterceptor;
import cn.sylinx.horm.util.GLog;

/**
 * 全局配置
 *
 * @author johnhan
 */
public enum OrmConfigHolder {

    INSTANCE;

    private final AtomicBoolean initialized = new AtomicBoolean(false);
    private OrmConfig ormConfig = new OrmConfig();
    private ServiceEnvironment serviceEnvironment = ServiceEnvironment.NORMAL;
    private SqlClientInterceptor sqlClientInterceptor = null;
    private CommandInterceptor commandInterceptor = null;
    private MapperInterceptor mapperInterceptor = null;

    public static synchronized void init(ServiceEnvironment serviceEnvironment, OrmConfig ormConfig) {

        if (INSTANCE.initialized.get()) {
            GLog.info("已初始化");
            return;
        }

        try {
            initInner(serviceEnvironment, ormConfig);
        } catch (Exception e) {
            GLog.error("初始化异常", e);
            throw new HORMException("初始化异常", e);
        } finally {
            INSTANCE.initialized.set(true);
        }
    }

    private static void initInner(ServiceEnvironment serviceEnvironment, OrmConfig ormConfig) {
        INSTANCE.serviceEnvironment = serviceEnvironment;
        INSTANCE.ormConfig = (OrmConfig) ormConfig.clone();
        initConfig();
        GLog.info("配置初始化成功, OrmConifg:{}", INSTANCE.ormConfig);
    }

    private static void initConfig() {

        if (isNormalJavaEnv()) {
            // 加载command
            new CommandLoader(INSTANCE.ormConfig).load();
            // 加载mapper
            new MapperLoader(INSTANCE.ormConfig).load();
            // jdbc事务隔离级别
            new TransactionIsolationLoader(INSTANCE.ormConfig).load();
        }

        // 加载模型映射策略
        new MapStrategyLoader(INSTANCE.ormConfig).load();

        // 加载模型到缓存
        if (isNormalJavaEnv() && !isDebug() && INSTANCE.ormConfig.isCacheModelOnStart()) {
            new ModelCacheLoader(INSTANCE.ormConfig).load();
        }

        // 拦截器 --> SqlClient
        INSTANCE.sqlClientInterceptor = new SqlClientInterceptorLoader(INSTANCE.ormConfig).load();
        // 拦截器 --> Command
        INSTANCE.commandInterceptor = new CommandInterceptorLoader(INSTANCE.ormConfig).load();
        // 拦截器 --> Mapper
        INSTANCE.mapperInterceptor = new MapperInterceptorLoader(INSTANCE.ormConfig).load();

        if (isSqlStatOpen()) {
            // sql统计
            SqlStatManager.start();
        }

    }

    /**
     * 返回克隆对象
     *
     * @return
     */
    public static OrmConfig getOrmConfig() {
        return (OrmConfig) INSTANCE.ormConfig.clone();
    }

    private static boolean isNormalJavaEnv() {
        return ServiceEnvironment.NORMAL == INSTANCE.serviceEnvironment;
    }

    public static ServiceEnvironment getServiceEnvironment() {
        return INSTANCE.serviceEnvironment;
    }

    public static String getParseSqlType() {
        return INSTANCE.ormConfig.getParseSqlType();
    }

    public static boolean isDebug() {
        return INSTANCE.ormConfig.isDebug();
    }

    public static boolean isCacheKeyMd5() {
        return INSTANCE.ormConfig.isCacheKeyMd5();
    }

    public static boolean isSqlStatOpen() {
        return INSTANCE.ormConfig.isSqlStatOpen()
                && (INSTANCE.ormConfig.getSqlExecuteTimeThreshold() > OrmConfig.DEFAULT_STAT_INTERNAL);
    }

    public static boolean isOptimisticLockEnable() {
        return INSTANCE.ormConfig.isOptimisticLockEnable();
    }

    public static boolean isCaseSensitive() {
        return INSTANCE.ormConfig.isCaseSensitive();
    }

    public static boolean isPrintSqlUseTime() {
        return INSTANCE.ormConfig.isPrintSqlUseTime();
    }

    public static long getSqlExecuteTimeThreshold() {
        return INSTANCE.ormConfig.getSqlExecuteTimeThreshold();
    }

    public static SqlClientInterceptor getSqlClientInterceptor() {
        return INSTANCE.sqlClientInterceptor;
    }

    public static boolean hasSqlClientInterceptor() {
        return INSTANCE.sqlClientInterceptor != null;
    }

    public static CommandInterceptor getCommandInterceptor() {
        return INSTANCE.commandInterceptor;
    }

    public static boolean hasCommandInterceptor() {
        return INSTANCE.commandInterceptor != null;
    }

    public static MapperInterceptor getMapperInterceptor() {
        return INSTANCE.mapperInterceptor;
    }

    public static boolean hasMapperInterceptor() {
        return INSTANCE.mapperInterceptor != null;
    }

    public static String getSqlPostfix() {
        return INSTANCE.ormConfig.getSqlPostfix();
    }

}